/**
 * 作者：
 * 创建时间：2012-6-28 上午9:29:48
 */
package dragon.model.table;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import dragon.core.exception.ExceptionHandler;
import dragon.core.io.FileHandler;
import dragon.core.io.XMLHandler;
import dragon.core.util.FilePath;
import dragon.core.util.StringUtils;
import dragon.model.base.Util;
import dragon.model.fieldTemplate.FieldTemplate;
import dragon.model.fieldTemplate.FieldTemplateContainer;

/**
 * 数据模型解析
 */
public class TableParser {

	/**
	 * 日志对象
	 */
	private static Logger logger = LoggerFactory.getLogger(TableParser.class);

	/**
	 * 解析数据模型对象
	 * 
	 * @param filePath
	 *            数据模型xml配置文件路径
	 * @return
	 * @throws ExceptionHandler
	 */
	@SuppressWarnings("unchecked")
	public static Table parse(String filePath) throws ExceptionHandler {

		// 构造文件路径
		if (logger.isDebugEnabled()) {
			logger.debug("获取数据模型，文件路径：" + filePath + " 存在：" + FileHandler.isFileExists(filePath));
		}

		// 文件不存在
		if (!FileHandler.isFileExists(filePath)) {
			return null;
		}

		// 解析文件内容，映射到对象
		List<Map<String, Object>> list = XMLHandler.readXML(filePath, "Table", null, true);
		if (list == null || list.size() == 0) {
			return null;// 文件不是有效的模型定义文件
		}

		Table table = new Table();
		if (FilePath.MODEL_TABLE.length() > filePath.lastIndexOf(FilePath.separator)) {
			table.setPkg("");
		} else {
			table.setPkg(filePath.substring(FilePath.MODEL_TABLE.length(), filePath.lastIndexOf(FilePath.separator)));
		}

		// 获取Table标签下的子级标签内容，这里默认了一个文件只存储一个模型定义(TODO:后期可改 )
		List<Map<String, Object>> children = (List<Map<String, Object>>) list.get(0).get(XMLHandler.CHILDREN_KEY);
		String tagName = null;
		String textContent = null;
		for (Map<String, Object> map : children) {
			tagName = (String) map.get(XMLHandler.TAG_NAME_KEY);
			textContent = null;
			if ("Fields".equalsIgnoreCase(tagName)) {
				/* 字段定义 */
				table.setFields(parseField(table, map));

				// 后续扩充
				DataType type = null;
				for (Field field : (List<Field>) table.getFields()) {
					type = field.getType();

					// 数值型字段 最大值，最小值 设定
					if (type.equals(DataType.INT2)) {
						// 有符号2字节整数
						if (field.getMaxValue() == null || StringUtils.isEmpty(field.getMaxValue())) {
							field.setMaxValue("32767");// 2^15-1
						}
						if (field.getMinValue() == null || StringUtils.isEmpty(field.getMinValue())) {
							field.setMinValue("-32768");// -2^15
						}
					} else if (type.equals(DataType.INT4)) {
						// 有符号4字节整数
						if (field.getMaxValue() == null || StringUtils.isEmpty(field.getMaxValue())) {
							field.setMaxValue("2147483647");
						}
						if (field.getMinValue() == null || StringUtils.isEmpty(field.getMinValue())) {
							field.setMinValue("-2147483648");
						}
					} else if (type.equals(DataType.INT8)) {
						// 有符号8字节整数
						if (field.getMaxValue() == null || StringUtils.isEmpty(field.getMaxValue())) {
							field.setMaxValue("9223372036854775807");
						}
						if (field.getMinValue() == null || StringUtils.isEmpty(field.getMinValue())) {
							field.setMinValue("-9223372036854775808");
						}
					}

					// 校验规则
					if (field.getValidType() == null || StringUtils.isEmpty(field.getValidType())) {
						// 文本型如果定义了长度则需要校验文本长度
						if (type.equals(DataType.CHAR) || type.equals(DataType.VARCHAR)) {
							if (field.getLength() > 0) {
								field.setValidType("validType=\"length[0," + field.getLength() + "]\"");
							}
						}
					}

					// TODO:其它规则
				}
				type = null;
			} else if (!StringUtils.isEmpty(tagName)) {
				/* 基本属性 */
				textContent = (String) map.get(XMLHandler.TEXT_CONTENT);
				Util.dynamicAssignment(table, tagName, textContent);
			}
		}

		return table;
	}

	/**
	 * 解析字段定义
	 * 
	 * @param table
	 *            数据模型对象
	 * @param map
	 *            以Fields为根的模型定义对象
	 * @return
	 * @throws ExceptionHandler
	 */
	@SuppressWarnings("unchecked")
	private static List<Field> parseField(Table table, Map<String, Object> map) throws ExceptionHandler {

		List<Field> list = new ArrayList<Field>();

		// 获取Fields下的节点
		String tagName = null;
		String textContent = null;
		FieldTemplate fieldTemplate = null;
		List<Map<String, Object>> fieldTags = (List<Map<String, Object>>) map.get(XMLHandler.CHILDREN_KEY);
		List<Map<String, Object>> fieldSubTags = null;
		Field field = null;

		for (Map<String, Object> fieldTag : fieldTags) {
			field = new Field();

			// 获取Field下的节点，解析Field属性
			fieldSubTags = (List<Map<String, Object>>) fieldTag.get(XMLHandler.CHILDREN_KEY);
			for (Map<String, Object> m : fieldSubTags) {
				tagName = (String) m.get(XMLHandler.TAG_NAME_KEY);
				textContent = (String) m.get(XMLHandler.TEXT_CONTENT);
				if ("Type".equalsIgnoreCase(tagName)) {
					// 数据类型
					field.setType(DataType.valueOf(textContent.toUpperCase()));
				} else if ("FieldTemplate".equalsIgnoreCase(tagName)) {
					if (textContent != null && !StringUtils.isEmpty(textContent)) {
						fieldTemplate = FieldTemplateContainer.get(textContent);
						if (fieldTemplate == null) {
							throw new ExceptionHandler(String.format("数据模型 %s[%s] 中字段 %s[%s] 引用的字段模板 %s 未定义", table.getName(), table.getCode(), field.getName(), field.getCode(), textContent));
						}
						try {
							field.setFieldTemplate(fieldTemplate.clone());
						} catch (CloneNotSupportedException e) {
						}
					}
				} else {
					// 其它基本属性
					Util.dynamicAssignment(field, tagName, textContent);
				}
			}

			field.setTable(table);// 反向绑定

			list.add(field);
		}

		field = null;
		fieldSubTags = null;
		fieldTags = null;
		fieldTemplate = null;
		textContent = null;
		tagName = null;

		return list;
	}
}
